package webrtc

import (
	"encoding/json"
	"errors"
	"fmt"
	"log"
	"time"

	"github.com/gofiber/websocket/v2"
	"github.com/pion/rtcp"
	"github.com/pion/rtp"
	"github.com/pion/webrtc/v3"
)

// 手机端连接使用该连接
func AndroidConn(c *websocket.Conn) (*PeerConnectionState, error) {

	newPeer := PeerConnectionState{
		PeerConnection: nil,
		Role:           Sender,
		Websocket: &ThreadSafeWriter{
			Conn: c,
			Send: make(chan []byte),
		}}
	return &newPeer, nil
}

func CreateRoom(roomId string, p *PeerConnectionState) error {
	RoomsLock.Lock()
	defer RoomsLock.Unlock()

	if room := Rooms[roomId]; room != nil {
		return errors.New("投屏码已被使用")
	}

	r := &Room{
		RoomId: roomId,
	}
	r.TrackLocals = make(map[string]*webrtc.TrackLocalStaticRTP)
	Rooms[roomId] = r
	err := AndroidRTCConn(p, r)
	if err != nil {
		log.Print(err.Error())
		return err
	}
	Peers[p] = r
	Rooms[roomId].SyncConnection()
	return nil
}

func AndroidRTCConn(peer *PeerConnectionState, room *Room) error {
	var config webrtc.Configuration
	// if os.Getenv("ENVIRONMENT") == "PRODUCTION" {
	// config = turnConfig
	// }
	peerConnection, err := webrtc.NewPeerConnection(config)
	if err != nil {
		log.Print(err)
		return err
	}
	// defer peerConnection.Close()

	for _, typ := range []webrtc.RTPCodecType{webrtc.RTPCodecTypeVideo, webrtc.RTPCodecTypeAudio} {
		if _, err := peerConnection.AddTransceiverFromKind(typ, webrtc.RTPTransceiverInit{
			Direction: webrtc.RTPTransceiverDirectionRecvonly,
		}); err != nil {
			log.Print(err)
			return err
		}
	}
	room.ListLock.Lock()
	room.Connections = append(room.Connections, peer)
	room.ListLock.Unlock()

	peer.PeerConnection = peerConnection
	peerConnection.OnICECandidate(func(i *webrtc.ICECandidate) {
		if i == nil {
			return
		}
		message, err := json.Marshal(SendMessage{
			Type: ICE,
			Data: i.ToJSON(),
		})
		if err != nil {
			log.Println(err)
			return
		}
		peer.Websocket.Send <- message
	})

	peerConnection.OnConnectionStateChange(func(pp webrtc.PeerConnectionState) {
		switch pp {
		case webrtc.PeerConnectionStateFailed:
			if err := peerConnection.Close(); err != nil {
				log.Print(err)
			}
		case webrtc.PeerConnectionStateClosed:
			// room.SignalPeerConnections()
		case webrtc.PeerConnectionStateDisconnected:
			fmt.Println("连接断开 Disconnected")
			peer.RTCStop()
		}
	})
	peerConnection.OnTrack(func(trackRemote *webrtc.TrackRemote, receiver *webrtc.RTPReceiver) {
		log.Printf("Track received: ID=%s, Codec=%s", trackRemote.ID(), trackRemote.Codec().MimeType)

		trackLocal := room.AddTrack(trackRemote)
		if trackLocal == nil {
			log.Println("AddTrack failed")
			return
		}

		// ✅ 马上同步，不等待
		go room.SyncConnection()

		// ✅ 更大 buffer，避免频繁分包
		go func() {
			rtpBuf := make([]byte, 20000)
			for {
				n, _, err := trackRemote.Read(rtpBuf)
				if err != nil {
					log.Println("ReadRTP error:", err)
					return
				}
				packet := &rtp.Packet{}
				if err := packet.Unmarshal(rtpBuf[:n]); err != nil {
					log.Println("Unmarshal error:", err)
					continue
				}
				if err := trackLocal.WriteRTP(packet); err != nil {
					log.Println("WriteRTP error:", err)
					return
				}
			}
		}()

		// ✅ 初始化发一次 PLI，然后降低频率
		go func() {
			// 初始化发一次 PLI
			time.Sleep(400 * time.Millisecond)
			_ = peerConnection.WriteRTCP([]rtcp.Packet{
				&rtcp.PictureLossIndication{
					MediaSSRC: uint32(trackRemote.SSRC()),
				},
			})

			ticker := time.NewTicker(2 * time.Second) // 5 秒一次就足够
			defer ticker.Stop()
			for range ticker.C {
				err := peerConnection.WriteRTCP([]rtcp.Packet{
					&rtcp.PictureLossIndication{
						MediaSSRC: uint32(trackRemote.SSRC()),
					},
				})
				if err != nil {
					log.Println("Send PLI failed:", err)
					return
				}
			}
		}()
	})

	return nil
}
